/**************************************************************************************
*  ADC.c
*
*  This file defines all native methods that have to be implemented to support
*  the class lpc2xxx/hw/ADC
*
*  Application developer should use the following functions to get access to
*  arrays and String object:
*       vmGetStringCount
*       vmGetStringArray
*       vmGetArraySize
*       vmGetArray
*  These functions are accessible via vm_config_t structure.
*
*  Native methods implementation
*  -----------------------------
*  Note that if the native method is NOT declared as static then param[0]
*  contains object's reference and must be skiped when accessing the native
*  method parameters.
**************************************************************************************
*
* This file is covered by the GNU GPL with the following exception:
*   As a special exception, the copyright holders of this library give you permission
*   to link this library with independent modules to produce an executable, regardless
*   of the license terms of these independent modules, and to copy and distribute the
*   resulting executable under terms of your choice, provided that you also meet, for
*   each linked independent module, the terms and conditions of the license of that
*   module. An independent module is a module which is not derived from or based on
*   this library. If you modify this library, you may extend this exception to your
*   version of the library, but you are not obligated to do so. If you do not wish
*   to do so, delete this exception statement from your version.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL RTJ COMPUTING BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2000-2006 RTJ Computing Pty. Ltd. All rights reserved.
**************************************************************************************/
#include <lpc2xxx.h>
#include "startup/config.h"
#include "javavm.h"

extern vm_config_t vmconfig;
extern volatile uint32 systemTimeMs;

#define CRYSTAL_FREQUENCY FOSC
#define PLL_FACTOR        PLL_MUL
#define VPBDIV_FACTOR     PBSD

#define VREF_IN_MV 2475

/****************************************************************************
* Performs AD conversion on the specified cannel.
****************************************************************************/
static uint32 get(uint32 ch)
{
	ADCR = (ADCR & 0xFFFFFF00) | (1 << ch) | (1 << 24);
	while ((ADDR & 0x80000000) == 0) 
        ;
	return (ADDR >> 6) & 0x3FF;
}

/****************************************************************************
* Initialises the ADC.
* On entry: n/a
*
* Java prototype:
*   private static native void init();
*
****************************************************************************/
int16 lpc2xxx_hw_ADC_init(int32 param[], int32 *retval)
{
    int tout = systemTimeMs + 5;

    ADCR = (1 << 0)                              |  //SEL = 1, dummy channel #1
            ((CRYSTAL_FREQUENCY * 
              PLL_FACTOR /
              VPBDIV_FACTOR) / 4500000 - 1) << 8 |  //set clock division factor, so ADC clock is 4.5MHz
            (0 << 16)                            |  //BURST = 0, conversions are SW controlled
            (0 << 17)                            |  //CLKS  = 0, 11 clocks = 10-bit result
            (1 << 21)                            |  //PDN   = 1, ADC is active
            (1 << 24)                            |  //START = 1, start a conversion now
            (0 << 27);							    //EDGE  = 0, not relevant when start=1

    while (tout > systemTimeMs)
        ;
    tout = ADDR;        // dummy read
    return NO_EXCEP;
}

/****************************************************************************
* Reads the analog value on specified channel
* On entry: param[0] - analog channel
*
* Java prototype:
*   private static native int get(int ad);
*
****************************************************************************/
int16 lpc2xxx_hw_ADC_get(int32 param[], int32 *retval)
{
    *retval = get(param[0]);
    return NO_EXCEP;
}

/****************************************************************************
* Reads the analog value on specified channel and returns it as mV
* On entry: param[0] - analog channel
*
* Java prototype:
*   private static native int getmV(int ad);
*
****************************************************************************/
int16 lpc2xxx_hw_ADC_getmV(int32 param[], int32 *retval)
{
    *retval = (get(param[0]) * VREF_IN_MV) / 1024;
    return NO_EXCEP;
}


